// node 33_数组中的find方法.js

// find()        查找一个数组里面第一个匹配元素(满足条件)的【 值 】，并进行返回
// findIndex()   查找一个数组里面第一个匹配元素(满足条件)的【索引】，并进行返回

// Object.defineProperty() 方法会直接在一个对象上定义一个新属性，或者修改一个对象的现有属性，并返回此对象。
// Object.defineProperty(要定义属性的对象, 要定义或修改的属性的名称或Symbol , 要定义或修改的属性描述符)

// Object() 创建一个新的 Object 对象。该对象将会包裹传入的参数
// new Error() 创建一个错误

// >>> 无符号右移 
//      会将目标转换为二进制，再将二进制右移相应的位数，再转为十进制输出
//      补1：能够将不是数字类型的值，转换成数字类型（如果不能转换，就转成0）
//      补2：能将不是正数的值，转变成正数


//find对数组元素进行删除
let dArr = [1,2,3,4,5,6]
dArr.find((i,index,arr)=>{//值被删除了，但还是会被遍历
    if(i === 3) {
        // delete arr[index]
        arr.pop()
    }
    console.log(i)
})

//手写find源码
Object.defineProperty(Array.prototype,'MyFind',{//在数组原型上写入方法
    value:function (fn) {
        if(this == null){//如果目标对象（数组）为空，则抛出错误
            return new Error('this 不能为null')
        }

        var o = Object(this)  //保持this
        var len = this.length >>> 0 //保持目标对象长度

        if(typeof fn !== 'function'){//如果接收的第一个参数不是函数（第一个参数作为手写find方法的回调函数），则抛出错误
            return new Error('fn必须是函数')
        }

        let then = arguments[1] //获取并保存接收的第二个参数，作为执行回调函数的this

        let k = 0
        while(k < len){
            let item = o[k]
            let res = fn.call(then,item,k,o)//使用call调用传入的函数，并接收返回值
            if(res) return item//如果返回值为true，则返回本次循环元素的值
            k++
        }
        return undefined//如果没有一个符合条件，则返回undefined
    }
});

//测试
let arr =  [1,2,3,4,5,6]
let res = arr.MyFind(function (p) {
    return p > 3
})
console.log(res)